use std::{env, fs};
use std::collections::HashMap;
use std::path::Path;

use dem::environment::{define, environment};
use dem::index::index;
use dem::runtime::runtime::path;
use dem::util::util::system::{lockpath, syscall};

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("Usage: {} 命令 [可选选项] [可选参数]", args[0]);
        println!("[dem help]获取可用的全部命令");

        return;
    }

    // 打印帮助信息
    if "help" == args[1] {
        help();

        return;
    }

    exec(&args[1..])
}

fn help() {
    let software = environment::get_project_used_software(false);

    if 0 == software.len() {
        println!("当前环境未配置工具，但是您仍可通过dem执行系统命令");

        return;
    }

    let mut commands: Vec<String> = Default::default();

    for (name, version) in software.iter() {
        let software = index::index().get(name);
        if software.is_none() {
            continue;
        }

        let software = software.unwrap();
        let version = software.get_version(version);
        if version.is_none() {
            continue;
        }

        let version = version.unwrap();
        let target = Path::new(path::DEM_SOFTWARE_PATH).join(name).join(version.version.as_str());

        for p in version.paths.iter() {
            let p = path::replace_package_tokens(p, target.to_str().unwrap(), version.version.as_str(), None);
            let entries = fs::read_dir(p);
            if entries.is_err() {
                continue;
            }

            for entry in entries.unwrap() {
                if entry.is_err() {
                    continue;
                }

                let filename = entry.unwrap().file_name();
                commands.push(filename.to_str().unwrap().to_string());
            }
        }
    }

    commands.sort();
    for command in commands {
        print!("{} ", command);
    }

    print!("\n");
}

fn exec(args: &[String]) {
    let software = environment::get_project_used_software(false);

    // 系统环境变量
    let mut environments: HashMap<String, String> = Default::default();
    for (key, value) in env::vars() {
        environments.insert(key, value);
    }

    let mut paths: Vec<String> = Default::default();
    for (name, version) in software.iter() {
        let software = index::index().get(name);
        if software.is_none() {
            continue;
        }

        let software = software.unwrap();
        let version = software.get_version(version);
        if version.is_none() {
            continue;
        }

        let version = version.unwrap();
        let target = Path::new(path::DEM_SOFTWARE_PATH).join(name).join(version.version.as_str());

        // 搜索路径
        for p in version.paths.iter() {
            let p = path::replace_package_tokens(p, target.to_str().unwrap(), version.version.as_str(), None);
            paths.push(p);
        }

        // 索引预置环境变量
        for env in version.environments.iter() {
            let tokens: Vec<&str> = env.split("=").collect();
            environments.insert(tokens[0].trim().to_string(), path::replace_package_tokens(tokens[1].trim(), target.to_str().unwrap(), version.version.as_str(), None));
        }

        // 全局环境变量
        let envs = environment::global().get_environments(name);
        if envs.is_some() {
            for (key, value) in envs.unwrap() {
                environments.insert(key.to_string(), path::replace_package_tokens(value, target.to_str().unwrap(), version.version.as_str(), None));
            }
        }

        // 项目环境变量
        let envs = environment::project().get_environments(name);
        if envs.is_some() {
            for (key, value) in envs.unwrap() {
                // 被隐藏的变量从环境配置表中移除
                if define::NULL_VALUE == value {
                    environments.remove(key);

                    continue;
                }

                environments.insert(key.to_string(), path::replace_package_tokens(value, target.to_str().unwrap(), version.version.as_str(), None));
            }
        }
    }

    let command = lockpath::lock_path(args[0].as_str(), &paths);
    if command.is_err() {
        println!("查找命令失败: {}", command.unwrap_err());

        return;
    }

    environments.insert("PATH".to_string(), paths.join(":").to_string() + ":" + env::var("PATH").unwrap().as_str());
    let working = env::current_dir().unwrap();

    // 预处理命令参数
    let mut nargs: Vec<String> = Vec::new();
    for i in 0..args.len() {
        let mut arg = args[i].to_string();

        if arg.starts_with("demrs:") {
            arg = format!("'{}'", arg.strip_prefix("demrs:").unwrap());
        }

        if arg.starts_with("demqs:") {
            arg = format!("\"{}\"", arg.strip_prefix("demqs:").unwrap());
        }

        nargs.push(arg)
    }

    // 执行环境内命令
    let command = command.unwrap();
    if command.is_some() {
        let command = command.unwrap() + " " + nargs[1..].join(" ").as_str();
        let result = syscall::execute_system_command(command.as_str(), Some(working.to_str().unwrap()), Some(&environments));
        if result.is_err() {
            println!("执行命令失败: {}", result.unwrap_err());

            return;
        }

        return;
    }

    // 执行普通命令
    let command = nargs.join(" ");
    let result = syscall::execute_system_command(command.as_str(), Some(working.to_str().unwrap()), Some(&environments));
    if result.is_err() {
        println!("执行命令失败: {}", result.unwrap_err());

        return;
    }
}